/**********************************************************************

  Audacity: A Digital Audio Editor

  AudioIOSequences.h

  Paul Licameli

  @brief interfaces for playable and recordable sample channel groups

**********************************************************************/
#ifndef __AUDACITY_AUDIO_IO_SEQUENCES__
#define __AUDACITY_AUDIO_IO_SEQUENCES__

#include "WideSampleSequence.h"
class ChannelGroup;

/*!
 Extends the interface for random access into a sample stream with tests for
 muting and solo
 */
struct MIXER_API PlayableSequence : WideSampleSequence {
    ~PlayableSequence() override;

    //! Find associated ChannelGroup if any
    virtual const ChannelGroup* FindChannelGroup() const = 0;

    //! May vary asynchronously
    virtual bool GetSolo() const = 0;

    //! May vary asynchronously
    virtual bool GetMute() const = 0;
};

using ConstPlayableSequences
    =std::vector<std::shared_ptr<const PlayableSequence> >;

/*!
 An interface for recording, by appending sequentially
 (but it also requires random access for insertion of silence)
 */
struct MIXER_API RecordableSequence {
    virtual ~RecordableSequence();
    virtual sampleFormat GetSampleFormat() const = 0;
    virtual double GetRate() const = 0;

    //! A constant property
    /*!
     @post result: `result > 0`
     */
    virtual size_t NChannels() const = 0;

    /** @brief Append the sample data to the track. You must call Flush()
     after the last Append.
     @pre `iChannel < NChannels()`
     @return true in case a block was flushed from memory to underlying DB
     */
    virtual bool Append(size_t iChannel, constSamplePtr buffer, sampleFormat format, size_t len, unsigned int stride, sampleFormat effectiveFormat /*!<
         Make the effective format of the data at least the minumum of this
         value and `format`.  (Maybe wider, if merging with preexistent data.)
         If the data are later narrowed from stored format, but not narrower
         than the effective, then no dithering will occur.
      */
                        ) = 0;

    //! Flush must be called after last Append
    virtual void Flush() = 0;

    //! Called in exception handling after possibly unbalanced calls to Append
    //! in different channels. Allows the sequence to repair consistency.
    virtual void RepairChannels() = 0;

    virtual void InsertSilence(double t, double len) = 0;

    virtual int64_t GetRecordableSequenceId() const = 0;
};

using RecordableSequences = std::vector<std::shared_ptr<RecordableSequence> >;

//! This is defined just to enable `dynamic_cast` on it
class MIXER_API OtherPlayableSequence
{
public:
    virtual ~OtherPlayableSequence();
};

struct MIXER_API TransportSequences final {
    ConstPlayableSequences playbackSequences;
    RecordableSequences captureSequences;
    std::vector<std::shared_ptr<const OtherPlayableSequence> >
    otherPlayableSequences;

    // This is a subset of playbackSequences
    ConstPlayableSequences prerollSequences;
};

#endif
